<?php

/**
 * Конструктор форм
 *
 * @author tonatos
 */
class c_form_controller extends c_base_controller {

    //put your code here

    protected $module = "form";
    public $action = "";
    public $method = "POST";
    public $multipart=false;
    public $fields = array();
    public $errors = array();
    public $form_id;

    public $submit_text = "Отправить";

    public $ajax_upload_error;

    public function  __construct($form_id="form_controller") {
        parent::__construct();
        $this->form_id = $form_id;
    }

    public function set_field_ok($set_value) {
        foreach ($this->fields as $field) {
            $field->set_field_ok=$set_value;

        }
    }

    public function data_submitted(){
        global $modx;
        if (isset($_POST['cancel'])){
            $modx->sendRedirect($this->cancel[1]);
        }

        if (isset($_POST['submitted'])){
            foreach ($this->fields as $field){
                $field->set_value($_POST[$field->name]);
            }
            return true;
        }else{
            return false;
        }
    }

    public function is_validate() {

        $result=true;

        foreach ($this->fields as $field){
            
            if (!$field->check()){
                $errors[] = $field->error;
                $result=false;
            }
        }
        return $result;
    }

    public function show_form() {
        global $modx;
        $modx->regClientCSS("assets/snippets/mvc/data/form/style.css");

        $this->template->copy_vars($this);
        $this->template->show("show_form");
    }

    public function reg_ajax_check($action){
        global $modx;
        $modx->regClientStartupScript("assets/js/jquery-1.4.4.min.js");
        $modx->regClientStartupScript("assets/snippets/mvc/data/form/default.js");

        $this->template->copy_vars($this);
        $this->template->action = $action."/ajax_check";
        $js = $this->template->show("ajax_check",true);

        $modx->regClientStartupHTMLBlock($js);

    }

    public function add($name, $title, $description="", $required=false) {
        return $this->add_varchar($name, $title, $description, $required);
    }

    public function get_field($name){
        return $this->fields[$name];
    }

    public function get_data() {
        
        $result = array();

        foreach ($this->fields as $key => $row) {
            if (($key!="antispam")&&($key!="checkbot")&&!empty($key)){
                $result[$key] = $row->get_value();
            }
        }

        return $result;
    }

    public function set_data($data){

        if (is_object($data)){
            $data = (array)$data;
        }
        
        foreach ($this->fields as $key => $row) {
            if (($key!="antispam")&&($key!="checkbot")&&!empty($key)){
                if (isset($data[$key])){
                    $row->set_value($data[$key]);
                }
            }
        }
    }

    function add_varchar($name, $title, $description="", $required=false) {
        $this->fields[$name] = new cl_varcharfield($name, $title, $description, "varchar", $required);
        return $this->fields[$name];
    }

    function add_text($name, $title, $description="", $required=false) {
        $this->fields[$name] = new cl_varcharfield($name, $title, $description, "text", $required);
        return $this->fields[$name];
    }


    function add_checkbox($name, $title, $description="") {
        $this->fields[$name] = new cl_checkbox($name, $title, $description, "checkbox");
        return $this->fields[$name];
    }

    function add_password($name, $title, $description="", $required=false) {
        $this->fields[$name] = new cl_varcharfield($name, $title, $description, "password", $required);
        return $this->fields[$name];
    }

    function add_username($name, $title, $description="", $required=false) {
        $this->fields[$name] = new cl_usernamefield($name, $title, $description, "varchar", $required);
        return $this->fields[$name];
    }

    function add_radio($name, $title, $description="", $required=false) {
        $this->fields[$name] = new cl_radiofield($name, $title, $description, "radio", $required);
        return $this->fields[$name];
    }

    function add_multi_checkbox($name, $title, $description="", $required=false) {
        $this->fields[$name] = new cl_multi_checkboxfield($name, $title, $description, "multi_checkbox", $required);
        return $this->fields[$name];
    }

    function add_email($name, $title, $description="", $required=false) {
        $this->fields[$name] = new cl_emailfield($name, $title, $description, "varchar", $required);
        return $this->fields[$name];
    }

    function add_antispam(){
        $this->fields["antispam"] = new cl_antispamfield();
        return $this->fields["antispam"];
    }

    function add_checkbot(){
        $this->fields["checkbot"] = new cl_checkbotfield();
        return $this->fields["checkbot"];
        
    }

    function add_hidden($name){
        $this->fields[$name]= new cl_varcharfield($name, "", "", "hidden", false);
        return $this->fields[$name];
    }

    function add_custom($name,$obj){
        $this->fields[$name]= $obj;
        return $this->fields[$name];
    }

    function add_html($html){
        $field = new cl_htmlfield($html);
        $this->fields[]= $field;
        return $field;
    }

    function add_cancel($url,$title="Назад"){
        $this->cancel = array($title,$url);
    }

    function add_date($name, $title, $description="", $required=false, $jqueryui=false) {
        global $modx;

        if ($jqueryui){
            //Регистрируем библиотеки
            $modx->regClientStartupScript("assets/js/jquery-1.4.4.min.js");
            $modx->regClientCSS("images/smoothness/jquery-ui-1.8.6.custom.css");
            $modx->regClientStartupScript("assets/js/jquery-ui-1.8.6.custom.min.js");
            $modx->regClientStartupScript("assets/js/jquery.ui.datepicker-ru.js");
            $modx->regClientStartupHtmlBlock('<script type="text/javascript">
                jQuery(document).ready(function($) {
                    $( ".datepicker" ).datepicker();
                    $( ".datepicker" ).datepicker("option", "changeYear", true );
                    $( ".datepicker" ).datepicker("option", "changeMonth", true );

                });</script>');
        }

        $this->fields[$name]= new cl_datefield($name, $title, $description, "date", $required);
        return $this->fields[$name];
        
    }

    function add_image($name, $title, $description="", $required=false) {
        $this->fields[$name] = new cl_imagefield($name, $title, $description, "image", $required);
        return $this->fields[$name];
    }

    public function do_file_upload($field_name,$allow_type="all"){
        global $modx, $mvc;

        if (empty($field_name) && empty($_FILES[$field_name])) {
            $this->ajax_upload_error = 'Ошибка в параметрах загрузки';
            return false;
        }

        if (!empty($_FILES[$field_name]['error'])) {

            switch ($_FILES[$field_name]['error']) {

                case '1':
                    $error = 'The uploaded file exceeds the upload_max_filesize directive in php.ini';
                    break;
                case '2':
                    $error = 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
                    break;
                case '3':
                    $error = 'The uploaded file was only partially uploaded';
                    break;
                case '4':
                    $error = 'Выберите файл.';
                    break;
                case '6':
                    $error = 'Missing a temporary folder';
                    break;
                case '7':
                    $error = 'Failed to write file to disk';
                    break;
                case '8':
                    $error = 'File upload stopped by extension';
                    break;
                default:
                    $error = 'Неизвестная ошибка';
            }
            $this->ajax_upload_error = $error;
            return false;

        };

        if (empty($_FILES[$field_name]['tmp_name']) || $_FILES[$field_name]['tmp_name'] == 'none') {
            $this->ajax_upload_error = "Файл не загрузился".print_r($_FILES,true);
            return false;
        }

        if ($_FILES[$field_name]['size']>$modx->config['upload_maxsize']) {
            $this->ajax_upload_error = "Превышен размер загружаемого файла. Разрешено: ".$mvc->format_bytes($modx->config['upload_maxsize']);
            return false;
        }
        
        //Проверка на разрешенные типы файлов
        $filename=basename(str_replace("\\","/",$_FILES[$field_name]['name']));
        $lastdot=strrpos($filename,".");
        if ($lastdot===false) {
            $this->ajax_upload_error = "Неразрешенный к загрузке тип файла";
            return false;
        }

        $ext=strtolower(substr($filename,($lastdot+1)));
	$filename=substr($filename,0,$lastdot);

        $allow_ext = array();
        switch ($allow_type){
            case "images":
                $allow_ext = explode(",", $modx->config['upload_images']);
                break;
            case "media":
                $allow_ext = explode(",", $modx->config['upload_media']);
                break;
            case "flash":
                $allow_ext = explode(",", $modx->config['upload_flash']);
                break;
            case "files":
                $allow_ext = explode(",", $modx->config['upload_files']);
                break;
            default:
                $allow_ext = explode(",", $modx->config['upload_images'].",".$modx->config['upload_media'].",".
                    $modx->config['upload_flash'].",".$modx->config['upload_files']);
                break;
        }

        if (!in_array($ext, $allow_ext)){
            $this->ajax_upload_error = "Неразрешенный к загрузке тип файла";
            return false;
        }

        //Подгатавливаем дирректорию к загрузке
        $upload_path = "assets/cache/uploaded/";
        if (!file_exists(MODX_BASE_PATH.$upload_path)){
            mkdir(MODX_BASE_PATH.$upload_path);
        }

        $filename = md5(rand()).rand();

        if (is_uploaded_file($_FILES[$field_name]['tmp_name'])){
            if (!move_uploaded_file($_FILES[$field_name]['tmp_name'], MODX_BASE_PATH.$upload_path."$filename.$ext")){
                $this->ajax_upload_error = "Неизвестная ошибка";
                return false;
            }            
        }else{
            $this->ajax_upload_error = "Неизвестная ошибка";
            return false;
        };

        return $upload_path."$filename.$ext";
        
    }

    public function do_image_upload($field_name){
        return $this->do_file_upload($field_name,"image");
    }

    /**
     *
     * @global DocmentParser $modx
     * @param string $field_name
     * @return <type>
     */
    public function do_photoimage_upload($field_name){
        global $modx;

        //загружаем файл
        $result = $this->do_image_upload($field_name);
        if ($result===false) return false;

        //Кропим его на 100x100
        //require_once 'path/to/ThumbLib.inc.php';
        try {
             $thumb = PhpThumbFactory::create(MODX_BASE_PATH.$result);
        }catch (Exception $e){
             $this->ajax_upload_error = $e->getMessage();
             return false;
        }

        $filename = time().rand().".jpg";
        //Подгатавливаем путь для сохранения
        $path = "assets/images/webusers/";
        if (!file_exists(MODX_BASE_PATH.$path)){
            mkdir(MODX_BASE_PATH.$path);
        }
        $path .= $modx->getLoginUserId()."/";
        if (!file_exists(MODX_BASE_PATH.$path)){
            mkdir(MODX_BASE_PATH.$path);
        }
        
        $thumb->resize(200,400);
        $thumb->save($path.$filename,"JPG");

        $thumb->adaptiveResizeQuadrant(100,100);
        $thumb->save($path."tn_".$filename,"JPG");

        $thumb->adaptiveResizeQuadrant(50,50);
        $thumb->save($path."small_".$filename,"JPG");

        return $path.$filename;

    }

    function add_photoimage($name, $title, $description="", $required=false) {
        
        global $modx;

        $this->multipart=true;

        $modx->regClientStartupScript("assets/js/jquery-1.4.4.min.js");
        $modx->regClientStartupScript("assets/snippets/mvc/data/form/ajaxfileuploader/ajaxfileupload.js");
        $modx->regClientStartupScript("assets/js/jquery.corner.js");
        $modx->regClientStartupScript("assets/libs/fancybox/jquery.fancybox-1.3.4.js");
        $modx->regClientStartupScript("assets/libs/fancybox/dr.fancybox.js");
        $modx->regClientCSS("assets/libs/fancybox/jquery.fancybox-1.3.4.css");

        $modx->regClientStartupHtmlBlock("<script type=\"text/javascript\">

function ajax_file_upload()
{
    jQuery('#loading').ajaxStart(function(){
        jQuery(this).show();
    })
    .ajaxComplete(function(){
        jQuery(this).hide();
    });

    jQuery('#buttonUpload').ajaxStart(function(){
        jQuery(this).attr('disabled','disabled');
    })
    .ajaxComplete(function(){
        jQuery(this).removeAttr('disabled');
    });


    jQuery.ajaxFileUpload (
    {
        url:'/assets/snippets/mvc/workplace/do_ajax_fileupload/file_to_upload_$name/',
        secureuri:false,
        fileElementId:'file_to_upload_$name',
        dataType: 'json',
        success: function (data, status){
            if(typeof(data.error) != 'undefined'){
                if(data.error != ''){
                    alert('Ошибка! '+data.error);
                }else{
                    jQuery('#id_field_$name').val(data.msg);
                    jQuery('#img_field_$name').attr('src',data.thumb);
                    jQuery('#remove_$name').removeClass('hide');
                    jQuery.fancybox.close();
                }
            }
        },
        error: function (data, status, e)
        {
            alert(e);
        }
    }
    )

    return false;

}

        jQuery(document).ready(function($) {
            $('#upload_$name').fancybox({
                'href' : '#photo_upload_$name'
            });

            $('#remove_$name').click(function(){
                jQuery('#id_field_$name').val('');
                jQuery('#img_field_$name').attr('src','assets/snippets/mvc/data/workplace/avatar_100x100.jpg');
                jQuery('#remove_$name').addClass('hide');
                return false;
            });

        });</script>");

        //+++

        $this->fields[$name] = new cl_photoimagefield($name, $title, $description, "photoimage", $required);
        return $this->fields[$name];
    }


}

class cl_basefield {

    public $name;
    public $value;
    public $title;
    public $description;
    public $type;
    public $required;
    public $default;
    public $min;
    public $max;
    public $error;
    
    public $set_field_ok=false;
    public $is_ok;


    /**
     * Шаблонизатор
     * @var c_template
     */
    protected $template;

    function __construct($name, $title, $description, $type, $required=false) {
        $this->name = $name;
        $this->title = $title;
        $this->description = $description;
        $this->required = $required;
        $this->type = $type;

        $this->template = new c_template("form");
    }

    function set_min($value) {
        $this->min = $value;
    }

    function set_max($value) {
        $this->max = $value;
    }

    function set_default($default) {
        $this->default = $default;
        return $this;
    }

    function set_error($error){
        $this->error = $error;
    }

    public function set_value($value){
        $this->value = $value;
    }

    public function get_value(){
        return $this->value;
    }
    
    function show() {
        $this->template->copy_vars($this);
        $this->template->show($this->type);
    }

    function check() {
        if ($this->required) {
            $this->value = trim($this->value);
            if (empty($this->value)) {
                $this->error = "обязательное поле!";
                $this->is_ok=false;
                return false;
            }
        }

        if (!empty($this->min)){
            if (mb_strlen($this->value)<$this->min){
                $this->error = "Минимум $this->min символов";
                $this->is_ok=false;
                return false;                
            }
        }
        $this->is_ok=true;
        return true;
    }

    function get_check_ajax($action){
        return '$("#id_field_'.$this->name.'").keyup(function(){eval_ajax("action='.$action.'/'.$this->name.'/"+$(this).val());});';
    }
}


class cl_varcharfield   extends cl_basefield{

    public $allow_html = false;

    public function set_value($value) {
        parent::set_value($value);
        
        if ($this->allow_html==false){
            $this->value = strip_tags($this->value);
        }
    }
}

class cl_radiofield     extends cl_basefield{

    public $options;

    public function set_options($data){
        $this->options = $data;
    }

    public function get_options(){
        return $this->options;
    }

    public function get_value(){
        return (empty($this->value))?0:$this->value;
    }
}


class cl_multi_checkboxfield extends cl_basefield{

    public $options;

    public function set_options($data){
        $this->options = $data;
    }

    public function get_options(){
        return $this->options;
    }

    public function get_value(){
        return (empty($this->value))?array():$this->value;
    }

    public function set_value($value){
        if (empty($value)){
            $value=array();
        }
        $this->value = $value;
    }
}

class cl_checkbox extends cl_basefield{

}

class cl_usernamefield   extends cl_basefield{

    public function  check() {
        global $modx;
        $result = parent::check();
        if (!$result) return $result;

        //Проверяем по базе данных
        $row = $modx->db->get_record("web_users","upper(username)=upper('".$modx->db->escape($this->value)."') ");
        if ($row!==false){
            $this->error = "Такое имя используется";
            $this->is_ok=false;
            return false;
        }

        $this->is_ok=true;
        return true;
    }
}

class cl_antispamfield   extends cl_basefield{

    public function  __construct() {
        parent::__construct("firstname", "Тема", "", "antispam", false);
    }

    public function check() {
        if (!empty($this->value)){
            $this->error = " ";
            return false;
        }
        return true;
    }
}

class cl_checkbotfield   extends cl_basefield{

    public function  __construct() {
        parent::__construct("checkbot", "Подтвердите, что Вы человек:", "", "checkbot", false);

        session_start();

        if ( !isset($_SESSION['cbt_session']) ) { // generate random names for curent session.
                $_SESSION['cbt_session'] = $this->rnd();
                $_SESSION['first'] = $this->rnd();
                $_SESSION['second'] = $this->rnd();
                $_SESSION['third'] = $this->rnd();
                $_SESSION['selected'] = $this->rnd();
        }

    }

    function rnd() { // function for generation random session names.
	$length = 10;
	$chars = 'qwertyuiopasdfghjklzxcvbnm';
	$numChars = strlen($chars);
	$string = '';

	for ($i = 0; $i < $length; $i++) {
		$string .= substr($chars, rand(1, $numChars) - 1, 1);
	}
	return $string;
    }

    public function  show() {
        global $modx;

        $path = '/assets/snippets/mvc/data/form/checkbot/';

        $patterns = scandir(MODX_BASE_PATH.$path);

        foreach($patterns as $key=>$value){
            if (($value==".")||($value=="..")||(!is_dir(MODX_BASE_PATH.$path.$value))){
                unset($patterns[$key]);
            }
        }
        
        $cbt_imgPack = $patterns[array_rand($patterns)];
        
        $url_1 = $path. $cbt_imgPack .'/1.jpg';
        $url_2 = $path. $cbt_imgPack .'/2.jpg';
        $url_3 = $path. $cbt_imgPack .'/3.jpg';

        // add images in array and shuffle.
        $array = array( $url_1, $url_2, $url_3 );
        shuffle($array);

        $img_1 = $array[0];
        $img_2 = $array[1];
        $img_3 = $array[2];

        // find true image in array.
        $i = 0;
        while ( $array[$i] != $url_1 ) {
                $i++;
        }

        $_SESSION['true'] = $i+1; // true image

        //Чтобы обеспечить единый вид
        $modx->regClientCSS($path."Default/style.css");
        $modx->regClientStartupScript($path.'script.js');

        $this->description=file_get_contents(MODX_BASE_PATH . $path. $cbt_imgPack .'/text.ru.txt');

        //$this->checkbot_show();

        $this->img_1 = $img_1;
        $this->img_2 = $img_2;
        $this->img_3 = $img_3;

        
        return parent::show();
    }


    public function check() {
	if ( $_POST[$_SESSION['cbt_session']] != $_SESSION['cbt_session'] ) {
            $this->error = "Подтвердите что Вы человек";
            $this->is_ok=false;
            return false;
    	}

        if ( $_POST[$_SESSION['selected']] != $_SESSION['true'] ) {
            $this->error = "Подтвердите что Вы человек";
            $this->is_ok=false;
            return false;

        }
        $this->is_ok=true;
        return true;
    }
}

class cl_htmlfield extends cl_basefield{
    function __construct($html) {
        $this->html = $html;
        $this->type = "html";

        $this->template = new c_template("form");
    }
}
class cl_emailfield   extends cl_basefield{

    public $check_for_web_user = true;
    public $ignore;

    public function check_web_user($check){
        $this->check_for_web_user = $check;
    }

    public function  check() {

        $result = parent::check();
        if (!$result) return $result;
        
        if (!empty($this->value)){
            if (!eregi("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-ZА-Я]{2,7}$", $this->value)){
                $this->error = "Ошибочный email адрес";
                $this->is_ok=false;
                return  false;
            }

            //Проверка на игнор
            if (!empty($this->ignore)){
                if (mb_strtolower($this->ignore)==  mb_strtolower($this->value)){
                    $this->is_ok=true;
                    return true;
                }
            }

            //Проверяем по базе
            if ($this->check_for_web_user){
                global $modx;
                $result = $modx->db->get_record("web_user_attributes","upper(email)=upper('".$modx->db->escape($this->value)."') ");
                if (!empty($result)){
                        $this->error = "Такой email используется, если это Ваш email воспользуйтесь системой "."<a href=\"register/fogot/".htmlspecialchars($this->value)."\">восстановления пароля</a>";
                        $this->is_ok=false;
                        return false;
                }
            }
            
        }
        $this->is_ok=true;
        return true;
    }
}
class cl_lozinza_emailfield extends cl_emailfield{

    public $check_for_web_user = false;

    public function  check() {
        global $modx;
        $result = parent::check();
        if (!$result) return $result;

        if (!empty($this->value)){
            if (!eregi("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-ZА-Я]{2,7}$", $this->value)){
                $this->error = ERROR_EMAIL;
                $this->is_ok=false;
                return  false;
            }

            $result = $modx->db->get_record("web_user_attributes","upper(email)=upper('".$modx->db->escape($this->value)."') ");
            if (!empty($result)){
                $this->error = "Данный email используется в системе, если это Ваш email Вы можете <a href=\"[~[*id*]~]#\" id=\"a_merge_by_email\">объеденить аккаунты</a>";
                $this->is_ok=false;
                return false;
            }


        }
        $this->is_ok=true;
        return true;
    }
    function get_check_ajax($action){
        return '$("#id_field_'.$this->name.'").keyup(function(){eval_ajax("action='.$action.'/'.$this->name.'/"+$(this).val());});'.
               'jQuery("#a_merge_by_email").click(function(){jQuery("#id_field_merge_by_email").val(1);jQuery("#form_controller").submit(); return false});';
        
    }
   
}

class cl_datefield extends cl_basefield{

    public $unixtimestamp;
    
    function check() {

        $result = parent::check();
        if (!$result) return $result;

        if (!$this->required && empty($this->value)) {
            $this->is_ok = true;
            return true;
        }


        //Дополнительная проверка на корректность даты
	preg_match("/(0?[1-9]|[12][0-9]|3[01])\.(0?[1-9]|1[012])\.([0-9]{4})/i", $this->value, $result);
        if(checkdate($result[2],$result[1],$result[3])){
            //Хер знает из-за чего приходится обавлять 6 часов (хватилобы и 2), иначе modx видит как за прошлый день
            //(подозвреваю что это как то связано с часовыми поясами)
            $this->unixtimestamp = intval( mktime (6,0,0,(int)$result[2],(int)$result[1],(int)$result[3]));
            $this->is_ok=true;
            return true;
        }else{
            $this->error = "Неверный формат даты";
            $this->is_ok=false;
            return false;
        }
    }

    public function set_value($value){
        if (is_numeric($value)){
            if (!empty($value)){
                $this->unixtimestamp=$value;
                $value = strftime("%d.%m.%Y", $value);
            }else{
                $value="";
            }
        }
        $this->value = $value;
    }

    public function get_value(){
        return $this->unixtimestamp;
    }
}

class cl_imagefield extends cl_basefield{
    
}

class cl_photoimagefield extends cl_basefield{
    public $user_id;

    public function  __construct($name, $title, $description, $type, $required = false) {
        global $modx;
        parent::__construct($name, $title, $description, $type, $required);
        $this->user_id = $modx->getLoginUserId();
    }
}

?>
